home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / dskut / docp_1_1.zip / DOCP.C < prev    next >
C/C++ Source or Header  |  1992-05-04  |  57KB  |  2,401 lines

  1. /*
  2.     docp.c - Directory-Oriented CoPy
  3.  
  4.     Fancy file copy program for MS-DOS
  5.  
  6.     Copyright (c) 1992, Roy Bixler
  7.     Originally by: David Oertel
  8.     Atari ST port, overall cheez-whiz: Roy Bixler
  9.  
  10.     This program is free software; you can redistribute it and/or modify
  11.     it under the terms of the GNU General Public License as published by
  12.     the Free Software Foundation; either version 1, or (at your option)
  13.     any later version.
  14.  
  15.     This program is distributed in the hope that it will be useful,
  16.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.     GNU General Public License for more details.
  19.  
  20.     You should have received a copy of the GNU General Public License
  21.     along with this program; if not, write to the Free Software
  22.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  23.  
  24. */
  25.  
  26. #include <stdio.h>
  27. #include <conio.h>
  28. #include <io.h>
  29. #include <alloc.h>
  30. #include <stdlib.h>
  31. #include <string.h>
  32. #include <sys\stat.h>
  33. #include <dir.h>
  34. #include <dos.h>
  35. #include <fcntl.h>
  36. #include <ctype.h>
  37.  
  38. #define DOT_NOTATION(dir) !strcmp(dir, "\.")
  39.  
  40. #include "docp.h"
  41. #include "doc.h"
  42. #include "elib.h"
  43. #include "protypes.h"
  44.  
  45. #define OPT_LIST "abcdfghijlmnorstvwz?"
  46. #define GET_OPT_LIST "AaBbCcD:d:F:f:GgHhIiJjLlMmNnOoRrSsTtVvW:w:Zz?"
  47. #define DOT_NOTATION(dir) !strcmp(dir, "\.")
  48. #define MAX_BUF 0xfffeU
  49.  
  50. extern int Optind;
  51. extern char *optarg;
  52. long Options = 0L;
  53. char Cur_source_dir[FILENAME_MAX], Org_dest_dir[FILENAME_MAX];
  54. ENTRY *Ptr;
  55. void *Buf_ptr;
  56. void *File_buf;
  57. int Reading_flag;    /* set if 'reading:' has been printed last
  58.                      * reset if 'writing:' has been printed last */
  59.  
  60. /* modes of date compare via 'd' option */
  61. #define D_BEFORE 1
  62. #define D_ON 2
  63. #define D_AFTER 4
  64.  
  65. DATE_NODE *Fdate;        /* used to store date entered via 'd' option */
  66. TIME_NODE *Ftime;        /* used to store time entered via 'w' option */
  67.  
  68. FILE *From_file_ptr;    /* file containing file list ('-f' option) */
  69. int Retry = 0;        /* set if target disk is full and user chooses to
  70.                      * continue */
  71. int Copied_a_file = 0;    /* set if at least one file was copied */
  72.  
  73. ENTRY *Src_tab[HASH_TAB_SIZE]; /* contains source-file names */
  74. ENTRY *Dst_tab[HASH_TAB_SIZE]; /* contains destination-file names */
  75.  
  76.  
  77. typedef struct file_list {
  78.     char *string;
  79.     struct file_list *next;
  80. } STDIN_TOKEN;
  81.  
  82. /* linked list globals containing file list from stdin */
  83. STDIN_TOKEN *Stdin_list_head = NULL;
  84. STDIN_TOKEN *Stdin_list_tail = NULL;
  85. STDIN_TOKEN *Stdin_list_current = NULL;
  86.  
  87. void main(int argc, char *argv[])
  88.  
  89. {
  90.     char src_dir[MAXDIR];
  91.     char dst_dir[MAXDIR];
  92.     unsigned long buf_size;
  93.     int num_args;
  94.     char **argv_ptr;
  95.     char *all[2] = {"*.*", NULL};
  96.  
  97.     get_flags(argv, argc);
  98.     check_flags();
  99.     check_and_format_dirs(argc, argv, src_dir, dst_dir);
  100. #ifdef LATER
  101.     check_target_removeable(dst_dir);
  102. #else
  103.     Options |= O_TARGET_REMOVEABLE;  /* assume any disk is removeable */
  104. #endif
  105.     File_buf = get_file_buf(&buf_size);
  106.     Buf_ptr = File_buf;
  107.     argv += Optind + 2;
  108.     num_args = argc - Optind - 2;
  109.     argv_ptr = argv;
  110.     if (Options & O_FROM_STDIN)
  111.         build_stdin_file_list(&num_args);
  112.     else if (Options & O_FROM_FILE) {
  113.         char buf[80];
  114.  
  115.         num_args = 0;
  116.         while (fgets(buf, 79, From_file_ptr) != NULL)
  117.             num_args++;
  118.         rewind(From_file_ptr);
  119.     } else if (num_args == 0) {
  120.         num_args = 1;
  121.         argv_ptr = all;
  122.     }
  123.     strcpy(Org_dest_dir, dst_dir);
  124.     if (Options & O_CHECK)
  125.         fprintf(stdout, "The following files would be copied or moved:\n");
  126.     else if (Options & O_ZAPTARGET)
  127.         zap_target(dst_dir, 1);
  128.     copy_files(src_dir, dst_dir, argv_ptr,
  129.                num_args, File_buf, buf_size);
  130.     write_buffer(File_buf);
  131.     clear_archive_bits(src_dir);
  132.  
  133.     if (!Copied_a_file)
  134.         fprintf(stdout, "no files copied\n");
  135.  
  136.     farfree(File_buf);
  137.  
  138. }
  139.  
  140. /*
  141.  *    check_and_format_dirs()
  142.  *
  143.  *    Input:
  144.  *        argc - command line argument count
  145.  *        argv - command line arguments
  146.  *        Optind - argument index from getopt()
  147.  *    Output:
  148.  *        src_dir - source directory name
  149.  *        dst_dir - destination directory name
  150.  *    Comments:
  151.  *        The source and destination directories are formatted
  152.  *        The source directory is checked for existence
  153.  *        The destination directory is created if it doesn't exist
  154.  *        The two directories are checked to insure that they are
  155.  *            different
  156.  *        The destination is checked to insure that it is not a
  157.  *            subdirectory of the source
  158.  */
  159.  
  160. void check_and_format_dirs(int argc, char *argv[],
  161.                            char *src_dir, char *dst_dir)
  162.  
  163. {
  164.     if ((argc-Optind) < 2)
  165.         usage();
  166.  
  167.     strcpy(src_dir, argv[Optind]);
  168.     check_if_dir_exists(src_dir, 0);
  169.     strcpy(dst_dir, argv[Optind + 1]);
  170.     check_if_dir_exists(dst_dir, 1);
  171.  
  172.     format_dir(argv[Optind], '\1', src_dir);
  173.     format_dir(argv[Optind + 1], '\1', dst_dir);
  174.  
  175.     check_if_dirs_compatible(src_dir, dst_dir);
  176. }
  177.  
  178. #ifdef LATER
  179. /*
  180.  *    check_target_removeable()
  181.  *
  182.  *    Input:
  183.  *        dst_dir - destination directory name
  184.  *    Output:
  185.  *        Options - will be modified if target directory is removeable
  186.  *                  (i.e. a floppy disk)
  187.  */
  188.  
  189. void check_target_removeable(char *dst_dir)
  190.  
  191. {
  192.     char dst_drive;
  193.  
  194.     if (islower(dst_drive = dst_dir[0]))
  195.         dst_drive = toupper(dst_drive);
  196.     if ((dst_drive == 'A') || (dst_drive == 'B'))
  197.         Options |= O_TARGET_REMOVEABLE;
  198. }
  199. #endif
  200.  
  201. /*
  202.  *    check_if_dirs_compatible()
  203.  *
  204.  *    Input:
  205.  *        src_dir - The formatted source directory name
  206.  *        dst_dir - The formatted destination directory name
  207.  *    Comments:
  208.  *        terminates if:
  209.  *            1 - The two directories are the same
  210.  *            2 - The destination is a subdirectory of
  211.  *                the source
  212.  */
  213.  
  214. void check_if_dirs_compatible(char *src_dir, char *dst_dir)
  215.  
  216. {
  217.     if (Options & O_CHECK)
  218.         return;
  219.     if (!strcmp(src_dir, dst_dir)) {
  220.         fprintf(stderr,
  221.             "source and destination directories are the same\n");
  222.         exit(-1);
  223.     }
  224.     if ((Options & O_RECURSIVE) &&
  225.         !strncmp(src_dir, dst_dir, strlen(src_dir))) {
  226.         fprintf(stderr,
  227.             "destination directory is a subdirectory of the source directory \nwhile in recursive mode\n");
  228.         exit(-1);
  229.     }
  230. }
  231.  
  232. /*
  233.  *    check_if_dir_exists()
  234.  *
  235.  *    Input:
  236.  *        dir - the directory name
  237.  *        is_dest - flag set if directory is a destination directory
  238.  *    Comments:
  239.  *        creates destination directory if it doesn't exist
  240.  *        terminates if the source directory doesn't exist
  241.  */
  242.  
  243. void check_if_dir_exists(char *dir, int is_dest)
  244.  
  245. {
  246.     int retval;
  247.     char *ext_path = append_dir_to_path(dir, "*.*");
  248.     struct ffblk tmp;
  249.  
  250.     if ((!just_disk(dir)) && (findfirst(ext_path, &tmp, FA_DIREC)))
  251.         if ((is_dest) && ((Options & O_BATCH) ||
  252.                           (printf("directory %s does not exist - ", dir),
  253.                            ask_user("create it (Y/N/Q) ? "))))
  254.             create_dir(dir);
  255.         else {
  256.             printf("docp: directory '%s' does not exist\n", dir);
  257.             exit(-1);
  258.         }
  259.     free(ext_path);
  260. }
  261.  
  262.  
  263. /*
  264.  *    create_dir()
  265.  *
  266.  *    Input:
  267.  *        dir - the directory to be created
  268.  *        options - command line options
  269.  *    Comments:
  270.  *        creates destination directory
  271.  */
  272.  
  273. void create_dir(char *dir)
  274.  
  275. {
  276.     char next_dir[MAXDIR], *p;
  277.  
  278.     strcpy(next_dir, dir);
  279.     for (p=next_dir; *p; p++)
  280.         if (*p == '/')
  281.             *p = '\\';
  282.  
  283.     p = next_dir;
  284.     while ((p = strchr(p, '\\')) != NULL) {
  285.         *p = '\0';
  286.         mkdir(next_dir);
  287.         *p++ = '\\';
  288.     }
  289.     if (mkdir(dir) == -1) {
  290.         fprintf(stderr, "cannot create directory '%s'\n", dir);
  291.         exit(-1);
  292.     }
  293.     else if (Options & O_VERBOSE)
  294.         printf("created directory '%s'\n", dir);
  295. }
  296.  
  297.  
  298. /*
  299.  *    just_disk()
  300.  *
  301.  *    Input:
  302.  *        dir - the directory to be checked
  303.  *    Output:
  304.  *        returns :
  305.  *            1 - if 'dir' is a "just" a directory specification of the
  306.  *                form 'X:', 'X:\' or 'X:/'
  307.  *            0 - otherwise
  308.  */
  309.  
  310. int just_disk(char *dir)
  311.  
  312. {
  313.     if (dir == NULL)
  314.         return 0;
  315.     switch (strlen(dir)) {
  316.       case 1:
  317.         return ((dir[0] == '/') || (dir[0] == '\\'));
  318.       case 2:
  319.         return ((isalpha(dir[0])) && (dir[1] == ':'));
  320.       case 3:
  321.         return ((isalpha(dir[0])) && (dir[1] == ':') &&
  322.                 ((dir[2] == '/') || (dir[2] == '\\')));
  323.       default:
  324.         return 0;
  325.     }
  326. }
  327.  
  328. /*
  329.  *    change_disk()
  330.  *
  331.  *    Input:
  332.  *        dir - the destination directory
  333.  *        curdir - the current working directo